﻿namespace Services
{
    public interface IQuery<TEntity>
        where TEntity : BaseEntity, new()
    {
        ISugarQueryable<TEntity> GetQueryable();
        TEntity GetByID(int id);
        TEntity GetModel(Expressionable<TEntity> where, string orderBy = null, ISugarQueryable<TEntity> fs = null);
        List<TEntity> GetAll(string orderBy = null, ISugarQueryable<TEntity> fs = null);
        List<TEntity> GetSearch(Expressionable<TEntity> where, string orderBy = null, int? top = null, ISugarQueryable<TEntity> fs = null);
        (List<TEntity> items, int totalCount) GetPage(Expressionable<TEntity> where, int pageIndex = 1, int pageSize = Gx._PAGE_SIZE, string orderBy = null, ISugarQueryable<TEntity> fs = null);
        int GetCount(Expressionable<TEntity> where, ISugarQueryable<TEntity> fs = null);
        TEntity GetModelBySQL(string sql, List<SugarParameter> values = null);
        List<TEntity> GetSearchBySQL(string sql, List<SugarParameter> values = null);
        int GetCountBySQL(string sql, List<SugarParameter> values = null);
    }

    public class BaseQuery<TEntity> : IQuery<TEntity>
        where TEntity : BaseEntity, new()
    {
        #region Ioc
        private readonly ISqlSugarClient _DB;
        private readonly ICurrentUser _currentUser;

        public BaseQuery(ISqlSugarClient dB, ICurrentUser currentUser)
        {
            _DB = dB;
            _currentUser = currentUser;
        }
        #endregion

        #region GetQueryable
        public ISugarQueryable<TEntity> GetQueryable()
        {
            return _DB.Queryable<TEntity>();
        }
        #endregion

        #region GetByID
        //TODO:试试在这个方法上能不能加上fs的处理
        public TEntity GetByID(int id)
        {
            var _query = GetQueryable();

            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                var _where = Expressionable.Create<TEntity>();
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
                _query.Where(_where.ToExpression());
            }

            return _query.InSingle(id);
        }
        #endregion

        #region GetModel
        public TEntity GetModel(Expressionable<TEntity> where, string orderBy = null, ISugarQueryable<TEntity> fs = null)
        {
            var _query = fs.IsEmpty() ? GetQueryable() : fs;

            var _where = where;
            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
            }

            _query.Where(_where.ToExpression());

            if (orderBy.IsNotEmpty())
            {
                _query.OrderBy(orderBy);
            }

            return _query.First();
        }
        #endregion

        #region GetAll
        public List<TEntity> GetAll(string orderBy = null, ISugarQueryable<TEntity> fs = null)
        {
            var _query = fs.IsEmpty() ? GetQueryable() : fs;

            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                var _where = Expressionable.Create<TEntity>();
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
                _query.Where(_where.ToExpression());
            }

            if (orderBy.IsNotEmpty())
            {
                _query.OrderBy(orderBy);
            }

            return _query.ToList();
        }
        #endregion

        #region GetSearch
        public List<TEntity> GetSearch(Expressionable<TEntity> where, string orderBy = null, int? top = null, ISugarQueryable<TEntity> fs = null)
        {
            var _query = fs.IsEmpty() ? GetQueryable() : fs;

            var _where = where;
            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
            }

            _query.Where(_where.ToExpression());

            if (orderBy.IsNotEmpty())
            {
                _query.OrderBy(orderBy);
            }

            if (top.HasValue && top.Value > 0)
            {
                _query.Take(top.Value);
            }

            return _query.ToList();
        }
        #endregion

        #region GetPage
        public (List<TEntity> items, int totalCount) GetPage(Expressionable<TEntity> where, int pageIndex = 1, int pageSize = Gx._PAGE_SIZE, string orderBy = null, ISugarQueryable<TEntity> fs = null)
        {
            var _query = fs.IsEmpty() ? GetQueryable() : fs;

            var _where = where;
            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
            }

            _query.Where(_where.ToExpression());

            if (orderBy.IsNotEmpty())
            {
                _query.OrderBy(orderBy);
            }

            int totalCount = 0;
            var list = _query.ToPageList(pageIndex, pageSize, ref totalCount);
            return (list, totalCount);
        }
        #endregion

        #region GetCount
        public int GetCount(Expressionable<TEntity> where, ISugarQueryable<TEntity> fs = null)
        {
            var _query = fs.IsEmpty() ? GetQueryable() : fs;

            var _where = where;
            var prop = typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY);
            if (prop.IsNotEmpty() && !prop.IsDefined(typeof(NotInDBAttribute), false) && _currentUser.CurrentUserInfo.LoginUserType == LoginUserType.集团)
            {
                _where = _where.And(x => x.GroupInfoID == _currentUser.CurrentUserInfo.LoginTypeID);
            }

            _query.Where(_where.ToExpression());

            return _query.Count();
        }
        #endregion

        #region GetModelBySQL
        public TEntity GetModelBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.SqlQuerySingle<TEntity>(sql, values);
        }
        #endregion

        #region GetSearchBySQL
        public List<TEntity> GetSearchBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.SqlQuery<TEntity>(sql, values);
        }
        #endregion

        #region GetCountBySQL
        public int GetCountBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.GetInt(sql, values);
        }
        #endregion
    }
}
